package org.summerframework.core.util;

import com.google.common.collect.Lists;
import org.summerframework.core.base.result.DefaultResultCode;
import org.summerframework.core.exception.WebException;
import org.summerframework.core.jackson.SelectByIdSerializer;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.cglib.beans.BeanMap;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 石超
 * @version v1.0.0
 */
public class ConvertUtils {
    private static final Map<String, BeanCopier> BEAN_COPIER_MAP = new HashMap<>();
    private static final Map<String, BeanMap> BEAN_MAP_MAP = new HashMap<>();

    public static <T> T copyProperties(Object source, Class<T> tClass) {
        try {
            return copyProperties(tClass.newInstance(), source);
        } catch (InstantiationException | IllegalAccessException e) {
            throw new WebException(DefaultResultCode.SYSTEM_ERROR, e);
        }
    }

    public static <T> T copyProperties(T t, Object source) {
        if (source == null) {
            return null;
        }

        beanCopier(source.getClass(), t.getClass()).copy(source, t, null);

        return SelectByIdSerializer.serializer(t);
    }

    public static <T> T copyProperties(Map<String, Object> source, Class<T> tClass) {
        try {
            return copyProperties(tClass.newInstance(), source);
        } catch (InstantiationException | IllegalAccessException e) {
            throw new WebException(DefaultResultCode.SYSTEM_ERROR, e);
        }
    }

    public static <T> T copyProperties(T t, Map<String, Object> source) {
        if (source == null) {
            return null;
        }

        BeanMap beanMap = BeanMap.create(t);
        beanMap.putAll(source);

        return (T) beanMap.getBean();
    }

    public static Map<String, Object> copyProperties(Object t) {
        if (t == null) {
            return null;
        }

        return BeanMap.create(t);
    }

    public static BeanCopier beanCopier(Class class1, Class class2) {
        String key = class1.getName() + "_" + class2.getName();
        return BEAN_COPIER_MAP.computeIfAbsent(key, key1 -> BeanCopier.create(class1, class2, false));
    }

    /**
     * 拷贝数组
     *
     * @param source      源数据
     * @param targetClass 目标对象模版
     * @return list the list
     * @author liaorb
     * @date 2019-05-30 14:46:10
     */
    public static <T> List<T> copyList(List<?> source, Class<T> targetClass) {
        if (source == null) {
            return null;
        } else {
            List<T> target = Lists.newArrayList();
            source.forEach(obj -> target.add(copyProperties(obj, targetClass)));
            return target;
        }
    }

    /**
     * 拷贝数组
     *
     * @param source 源数据
     * @param t      目标对象模版
     * @return list the list
     * @author liaorb
     * @date 2019-05-30 14:46:10
     */
    public static <T> List<T> copyList(List<?> source, T t) {
        if (source == null) {
            return null;
        } else {
            List<T> target = Lists.newArrayList();
            source.forEach(obj -> target.add(copyProperties(t, obj)));
            return target;
        }
    }
}
